package com.xiaouyudeguang.common.dicode.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.xiaouyudeguang.common.dicode.dao.DiCodeDao;
import com.xiaouyudeguang.common.dicode.entity.DiCode;
import com.xiaouyudeguang.common.dicode.service.DiCodeService;
import com.xiaouyudeguang.common.discript.service.DiScriptService;
import com.xiaouyudeguang.common.ditable.service.DiTableService;
import com.xiaouyudeguang.common.entity.BaseEntity;
import com.xiaouyudeguang.common.exception.BusinessException;
import com.xiaouyudeguang.common.message.event.ChangedEvent;
import com.xiaouyudeguang.common.message.pusher.IEventPusher;
import com.xiaouyudeguang.common.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

import static com.xiaouyudeguang.common.config.MybatisPlusConfig.TABLE_NAME;

@Slf4j
@Service
@Transactional
public class DiCodeServiceImpl extends ServiceImpl<DiCodeDao, DiCode> implements DiCodeService {

    protected Set<String> ignoreFields = Arrays.stream(BaseEntity.class.getDeclaredFields()).map(Field::getName).collect(Collectors.toSet());

    private static final String fragment = "json -> '$.\"%s\"'  %s %s";

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private DiCodeService baseService;

    @Autowired
    private DiTableService diTableService;

    @Autowired
    private DiScriptService discriptService;

    @Autowired
    private IEventPusher eventPusher;

    @Override
    public String save(String tenantId, String appId, String tableName, JsonNode request) throws Exception {
        DiCode data = DiCode.builder().id(String.valueOf(IdWorker.getId() / 1000)).appId(appId).tenantId(tenantId).json((ObjectNode) request.get("data")).build();
        eventPusher.publishEvent(ChangedEvent.Type.INSERT, tableName, save(data), data);
        return data.getId();
    }

    @Override
    public boolean saveBatch(String tenantId, String appId, String tableName, ArrayNode dataList) throws Exception {
        for (JsonNode data : dataList) {
            ObjectNode objectNode = JsonObject.createObjectNode();
            objectNode.set("data", data);
            save(tenantId, appId, tableName, objectNode);
        }
        return true;
    }

    @Override
    public boolean deleteById(String tenantId, String appId, String tableName, String id) throws BusinessException {
        return removeById(id);
    }

    @Override
    public boolean deleteByIds(String tenantId, String appId, String tableName, Set<String> ids) throws Exception {
        return removeBatchByIds(ids);
    }

    @Override
    public boolean updateById(String tenantId, String appId, String tableName, JsonNode request) throws Exception {
        ObjectNode data = (ObjectNode) request.get("data");
        DiCode dicode = getById(data.remove("id").asText());
        if (dicode == null) {
            throw new BusinessException("数据已不存在");
        }
        if (!appId.equals(tenantId) && !tenantId.equals(dicode.getTenantId())) {
            throw new BusinessException("没有操作权限");
        }
        DiCode source = CopyUtils.copy(dicode, DiCode.class);
        source.setJson(dicode.getJson().deepCopy());
        if (data.has("sort")) {
            dicode.setSort(data.remove("sort").asInt());
        }
        if (data.has("isDefault")) {
            dicode.setIsDefault(data.remove("isDefault").asBoolean());
        }
        dicode.getJson().setAll((ObjectNode) request.get("data"));
        return eventPusher.publishEvent(ChangedEvent.Type.UPDATE, tableName, updateById(dicode), source);
    }

    @Override
    public boolean updateByIds(String tenantId, String appId, String tableName, JsonNode request) throws Exception {
        ObjectNode data = (ObjectNode) request.get("data");
        for (JsonNode idNode : request.withArray("ids")) {
            data.set("id", idNode);
            updateById(tenantId, appId, tableName, request);
        }
        return true;
    }

    @Override
    public boolean updateBatch(String tenantId, String appId, String tableName, ArrayNode dataList) throws Exception {
        for (JsonNode data : dataList) {
            ObjectNode objectNode = JsonObject.createObjectNode();
            objectNode.set("data", data);
            updateById(tenantId, appId, tableName, objectNode);
        }
        return true;
    }

    @Override
    public JsonNode getById(String tenantId, String appId, String tableName, String id) throws Exception {
        DiCode data = getById(id);
        if (data == null || (!appId.equals(tenantId) && !tenantId.equals(data.getTenantId()))) {
            return null;
        }
        ObjectNode jsonNode = fillData(tenantId, appId, tableName, data.getJson());
        return jsonNode.setAll((ObjectNode) objectMapper.valueToTree(data));
    }

    @Override
    public List<ObjectNode> getByIds(String tenantId, String appId, String tableName, Set<String> ids) throws Exception {
        List<DiCode> dataList = listByIds(ids);
        List<ObjectNode> recordList = new ArrayList<>();
        for (DiCode data : dataList) {
            if (appId.equals(tenantId) || tenantId.equals(data.getTenantId())) {
                ObjectNode jsonNode = fillData(tenantId, appId, tableName, data.getJson());
                recordList.add(jsonNode.setAll((ObjectNode) objectMapper.valueToTree(data)));
            }
        }
        return recordList;
    }

    @Override
    public ObjectNode getOne(String tenantId, String appId, String tableName, JsonNode request) throws Exception {
        LambdaQueryWrapper<DiCode> lambdaQueryWrapper = lambdaWrapper(tenantId, appId, tableName, request);
        if (lambdaQueryWrapper == null) {
            return null;
        }
        DiCode data = getOne(lambdaQueryWrapper);
        if (data == null) {
            return null;
        }
        ObjectNode jsonNode = fillData(tenantId, appId, tableName, data.getJson());
        return jsonNode.setAll((ObjectNode) objectMapper.valueToTree(data));
    }

    @Override
    public List<ObjectNode> list(String tenantId, String appId, String tableName, JsonNode request) throws Exception {
        LambdaQueryWrapper<DiCode> lambdaQueryWrapper = lambdaWrapper(tenantId, appId, tableName, request);
        if (lambdaQueryWrapper == null) {
            return Collections.emptyList();
        }
        List<DiCode> dataList = list(lambdaQueryWrapper);
        List<ObjectNode> recordList = new ArrayList<>();
        for (DiCode data : dataList) {
            ObjectNode jsonNode = fillData(tenantId, appId, tableName, data.getJson());
            recordList.add(jsonNode.setAll((ObjectNode) objectMapper.valueToTree(data)));
        }
        return recordList;
    }

    @Override
    public List<ObjectNode> tree(String tenantId, String appId, String tableName, JsonNode request) throws Exception {
        LambdaQueryWrapper<DiCode> lambdaQueryWrapper = lambdaWrapper(tenantId, appId, tableName, request);
        if (lambdaQueryWrapper == null) {
            return Collections.emptyList();
        }
        List<DiCode> dataList = list(lambdaQueryWrapper);
        if (dataList.isEmpty()) {
            return Collections.emptyList();
        }
        fillParent(tenantId, appId, tableName, dataList);
        List<ObjectNode> recordList = new ArrayList<>();
        for (DiCode data : dataList) {
            ObjectNode jsonNode = fillData(tenantId, appId, tableName, data.getJson());
            recordList.add(jsonNode.setAll((ObjectNode) objectMapper.valueToTree(data)));
        }
        return toTree("0", recordList.stream().collect(Collectors.groupingBy(it -> it.path("pid").asText())));
    }

    private void fillParent(String tenantId, String tableName, String appId, List<DiCode> dataList) throws Exception {
        Set<String> ids = dataList.stream().map((DiCode::getId)).collect(Collectors.toSet());
        Set<String> pids = dataList.stream().map((it -> it.getJson().path("pid").asText())).filter(it -> !ids.contains(it)).collect(Collectors.toSet());
        if (!pids.isEmpty()) {
            List<DiCode> parentList = listByIds(pids);
            if (!parentList.isEmpty()) {
                dataList.addAll(parentList);
                fillParent(tenantId, appId, tableName, dataList);
            }
        }
    }

    private List<ObjectNode> toTree(String pid, Map<String, List<ObjectNode>> dataMap) {
        List<ObjectNode> nodeList = dataMap.get(pid);
        if (nodeList != null && !nodeList.isEmpty()) {
            nodeList.forEach(it -> {
                List<ObjectNode> childrens = toTree(it.path("id").asText(), dataMap);
                if (childrens != null && !childrens.isEmpty()) {
                    it.set("children", JsonObject.createArrayNode(childrens));
                }
            });
        }
        return nodeList;
    }

    @Override
    public Set<String> listIds(String tenantId, String appId, String tableName, JsonNode request) throws Exception {
        LambdaQueryWrapper<DiCode> lambdaQueryWrapper = lambdaWrapper(tenantId, appId, tableName, request);
        if (lambdaQueryWrapper == null) {
            return Collections.emptySet();
        }
        List<DiCode> dataList = list(lambdaQueryWrapper);
        return dataList.stream().map(DiCode::getId).collect(Collectors.toSet());
    }

    @Override
    public PageImpl<ObjectNode> page(String tenantId, String appId, String tableName, JsonNode request) throws Exception {
        LambdaQueryWrapper<DiCode> lambdaQueryWrapper = lambdaWrapper(tenantId, appId, tableName, request);
        if (lambdaQueryWrapper == null) {
            return new PageImpl<>(Collections.emptyList(), Pageable.unpaged(), 0);
        }
        long current = request.path("current").asLong(1);
        long size = request.path("size").asLong(10);
        Page<DiCode> page = page(Page.of(current, size), lambdaQueryWrapper);
        List<DiCode> dataList = page.getRecords();
        if (dataList.isEmpty()) {
            return new PageImpl<>(Collections.emptyList(), Pageable.unpaged(), 0);
        }
        List<ObjectNode> recordList = new ArrayList<>();
        for (DiCode data : dataList) {
            ObjectNode jsonNode = fillData(tenantId, appId, tableName, data.getJson());
            recordList.add(jsonNode.setAll((ObjectNode) objectMapper.valueToTree(data)));
        }
        return new PageImpl<>(recordList, Pageable.unpaged(), page.getTotal());
    }

    private LambdaQueryWrapper<DiCode> lambdaWrapper() {
        LambdaQueryWrapper<DiCode> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.orderByAsc(DiCode::getIsDefault);
        lambdaQueryWrapper.orderByAsc(DiCode::getSort);
        lambdaQueryWrapper.orderByDesc(DiCode::getCreated);
        return lambdaQueryWrapper;
    }

    private LambdaQueryWrapper<DiCode> lambdaWrapper(String tenantId, String appId, String tableName, JsonNode request) throws Exception {
        LambdaQueryWrapper<DiCode> lambdaQueryWrapper = lambdaWrapper();
        lambdaQueryWrapper.ge(request.has("startTime"), DiCode::getCreated, request.path("startTime").asText());
        lambdaQueryWrapper.le(request.has("endTime"), DiCode::getCreated, request.path("endTime").asText());
        if (appId.equals(tenantId)) {
            lambdaQueryWrapper.eq(DiCode::getAppId, appId);
        } else {
            lambdaQueryWrapper.eq(DiCode::getAppId, appId);
            lambdaQueryWrapper.eq(DiCode::getTenantId, tenantId);
        }
        JsonNode data = request.path("data");
        Iterator<Map.Entry<String, JsonNode>> fields = request.fields();
        if (request.has("data")) {
            fields = data.fields();
        }
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> entry = fields.next();
            if (StringUtils.isNotBlank(entry.getKey()) && entry.getValue() != null) {
                String key = entry.getKey();
                if (entry.getValue().isArray()) {
                    ArrayNode arrayNode = data.withArray(key);
                    if (arrayNode.size() == 2) {
                        if (arrayNode.path(0).isLong()) {
                            lambdaQueryWrapper.apply(String.format(fragment, key, ">=", replace(DateUtils.format(arrayNode.path(0).asLong()))));
                            lambdaQueryWrapper.apply(String.format(fragment, key, "<=", replace(DateUtils.format(arrayNode.path(1).asLong()))));
                        } else {
                            lambdaQueryWrapper.apply(String.format(fragment, key, ">=", replace(arrayNode.path(0).asText())));
                            lambdaQueryWrapper.apply(String.format(fragment, key, "<=", replace(arrayNode.path(1).asText())));
                        }
                    }
                } else {
                    String value = entry.getValue().asText();
                    if (StringUtils.startsWith(value, "_")) {
                        lambdaQueryWrapper.apply(String.format(fragment, key, "=", value.substring(1)));
                    } else if (StringUtils.startsWith(key, "_") && entry.getValue().getNodeType() == JsonNodeType.OBJECT) {
                        String linkedTableName = entry.getKey().substring(1);
                        TABLE_NAME.set(linkedTableName);
                        Set<String> linkedIds = baseService.listIds(tenantId, appId, linkedTableName, entry.getValue());
                        if (linkedIds.isEmpty()) {
                            return null;
                        }
                        lambdaQueryWrapper.apply(String.format(fragment, key, "in", "(" + format(linkedIds) + ")"));
                        TABLE_NAME.remove();
                    }
//                    else if (value.contains(",")) {
//                        if (value.replace(",", "").matches("[0-9]+")) {
//                            lambdaQueryWrapper.apply(String.format(fragment, key, "in", "(" + value + ")"));
//                        } else {
//                            lambdaQueryWrapper.apply(String.format(fragment, key, "in", "('" + value.replace(",", "', '") + "')"));
//                        }
//                    }
                    else if (value.startsWith("!") || value.startsWith("!=") || value.startsWith("ne.")) {
                        lambdaQueryWrapper.apply(String.format(fragment, key, "!=", replace(value)));
                    } else if (value.startsWith(">=") || value.startsWith("=>") || value.startsWith("ge.")) {
                        lambdaQueryWrapper.apply(String.format(fragment, key, ">=", replace(value)));
                    } else if (value.startsWith("<=") || value.startsWith("=<") || value.startsWith("le.")) {
                        lambdaQueryWrapper.apply(String.format(fragment, key, "<=", replace(value)));
                    } else if (value.startsWith(">") || value.startsWith("gt.")) {
                        lambdaQueryWrapper.apply(String.format(fragment, key, ">", replace(value)));
                    } else if (value.startsWith("<") || value.startsWith("lt.")) {
                        lambdaQueryWrapper.apply(String.format(fragment, key, "<", replace(value)));
                    } else {
                        lambdaQueryWrapper.apply(String.format(fragment, key, "like", "'%" + value.replace("like.", "").replace("%", "") + "%'"));
                    }
                }
            }
        }
        return lambdaQueryWrapper;
    }

    private static String format(Collection<?> collection) {
        StringBuilder sb = new StringBuilder();
        collection.forEach(c -> {
            sb.append(",'").append(c).append("'");
        });
        return sb.substring(1);
    }

    private String replace(String value) {
        value = value.replace("!", "")
                .replace("!=", "").replace("ne.", "")
                .replace("=", "").replace("eq.", "")
                .replace(">", "").replace("gt.", "")
                .replace(">=", "").replace("ge.", "")
                .replace("<", "").replace("lt.", "")
                .replace("<=", "").replace("le.", "")
                .replaceAll(" and ", "").replaceAll(" or ", "");
        return value.replaceFirst("\\u002E", "").matches("[0-9]+") ? value : "'" + value + "'";
    }

    private ObjectNode fillData(String tenantId, String appId, String tableName, ObjectNode jsonNode) throws Exception {
        ObjectNode bodyNode = jsonNode.deepCopy();
        Iterator<Map.Entry<String, JsonNode>> fields = bodyNode.fields();
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> entry = fields.next();
            if (StringUtils.startsWith(entry.getKey(), "_") && entry.getValue() != null) {
                String linkedTableName = entry.getKey().substring(1);
                if (entry.getValue().isArray()) {
                    StringBuilder idStr = new StringBuilder();
                    for (JsonNode valueNode : entry.getValue()) {
                        idStr.append(",").append(valueNode.asText());
                    }
                    TABLE_NAME.set(linkedTableName);
                    jsonNode.set(linkedTableName, objectMapper.createArrayNode().addAll(baseService.getByIds(tenantId, appId, linkedTableName, Sets.newHashSet(idStr.substring(1).split(",")))));
                    TABLE_NAME.remove();
                } else {
                    String idStr = entry.getValue().asText();
                    if (!Arrays.asList(tableName.split(",")).contains(linkedTableName)) {
                        TABLE_NAME.set(linkedTableName);
                        if (idStr.contains(",")) {
                            List<ObjectNode> nodeList = baseService.getByIds(tenantId, appId, linkedTableName, Sets.newHashSet(idStr.split(",")));
                            nodeList = toTree("0", nodeList.stream().collect(Collectors.groupingBy(it -> it.path("pid").asText())));
                            jsonNode.set(linkedTableName, objectMapper.createArrayNode().addAll(nodeList));
                        } else {
                            jsonNode.set(linkedTableName, baseService.getById(tenantId, appId, linkedTableName + "," + tableName, idStr));
                        }
                        TABLE_NAME.remove();
                    }
                }
            }
        }
        return jsonNode;
    }

    @Override
    public List<ObjectNode> export(String tenantId, String appId, String tableName, JsonNode request) throws Exception {
        tableName = StringUtils.lowerCamel(tableName);
        List<ObjectNode> dataList;
        if (request.has("ids")) {
            ArrayNode idsNode = (ArrayNode) request.get("ids");
            Set<String> ids = new HashSet<>();
            idsNode.forEach(header -> {
                ids.add(header.asText());
            });
            dataList = getByIds(tenantId, appId, tableName, ids);
        } else {
            dataList = page(tenantId, appId, tableName, request).getContent();
        }
        if (dataList.isEmpty()) {
            return dataList;
        }
        ObjectNode diTable = diTableService.getTable(tenantId, appId, tableName);
        if (diTable == null) {
            return dataList;
        }
        Iterator<Map.Entry<String, JsonNode>> fields = diTable.fields();
        while (fields.hasNext()) {
            Map.Entry<String, JsonNode> entry = fields.next();
            if (entry.getValue() != null && entry.getValue().get("comment") != null) {
                String comment = entry.getValue().get("comment").asText();
                dataList.forEach(it -> {
                    if (it.get(entry.getKey()) != null) {
                        it.set(comment, it.remove(entry.getKey()));
                    }
                });
            }
        }
        return dataList;
    }

    @Override
    public String upload(String tenantId, String appId, String tableName, List<Map<String, Object>> dataList) throws Exception {
        tableName = StringUtils.lowerCamel(tableName);
        Map<String, String> filedMap = new HashMap<>();
        ObjectNode diTable = diTableService.getTable(tenantId, appId, tableName);
        if (diTable != null) {
            Iterator<Map.Entry<String, JsonNode>> fields = diTable.fields();
            while (fields.hasNext()) {
                Map.Entry<String, JsonNode> entry = fields.next();
                if (entry.getValue() != null && entry.getValue().get("comment") != null) {
                    filedMap.put(entry.getValue().get("comment").asText(), entry.getKey());
                }
            }
        }
        for (Map<String, Object> data : dataList) {
            ObjectNode objectNode = objectMapper.createObjectNode();
            for (Map.Entry<String, Object> entry : data.entrySet()) {
                if (entry.getValue() != null) {
                    objectNode.set(filedMap.getOrDefault(entry.getKey(), entry.getKey()), objectMapper.readTree(objectMapper.writeValueAsString(entry.getValue())));
                }
            }
            save(tenantId, appId, tableName, objectMapper.createObjectNode().set("data", objectNode));
        }
        return null;
    }

    @Override
    public Boolean update(String tenantId, String appId, String tableName, String tableApi, JsonNode request) throws Exception {
        Map<String, Object> param = JsonObject.getMap(request, "data");
        param.put("asc", request.path("asc").asText());
        param.put("desc", request.path("desc").asText());
        String script = getScript(tenantId, appId, tableName, tableApi, param);
        if (StringUtils.isBlank(script)) {
            throw new BusinessException("功能暂不支持");
        }
        return baseMapper.update(script, param) > 0;
    }

    @Override
    public Boolean delete(String tenantId, String appId, String tableName, String tableApi, JsonNode request) throws Exception {
        Map<String, Object> param = JsonObject.getMap(request, "data");
        param.put("asc", request.path("asc").asText());
        param.put("desc", request.path("desc").asText());
        String script = getScript(tenantId, appId, tableName, tableApi, param);
        if (StringUtils.isBlank(script)) {
            throw new BusinessException("功能暂不支持");
        }
        return baseMapper.delete(script, param) > 0;
    }

    @Override
    public Object page(String tenantId, String appId, String tableName, String tableApi, JsonNode request) throws Exception {
        Map<String, Object> param = JsonObject.getMap(request, "data");
        param.put("asc", request.path("asc").asText());
        param.put("desc", request.path("desc").asText());
        String script = getScript(tenantId, appId, tableName, tableApi, param);
        if (StringUtils.isBlank(script)) {
            if ("page".equals(tableApi)) {
                return page(tenantId, appId, tableName, request);
            }
            if ("list".equals(tableApi)) {
                return list(tenantId, appId, tableName, request);
            }
            if ("getOne".equals(tableApi)) {
                return getOne(tenantId, appId, tableName, request);
            }
            throw new BusinessException("功能暂不支持");
        }
        if (tableApi.startsWith("get")) {
            Map<String, Object> result = baseMapper.getOne(script, param);
            if (result == null) {
                return null;
            }
            if (result.keySet().size() == ignoreFields.size() && !result.keySet().stream().filter(it -> !ignoreFields.contains(it)).collect(Collectors.toSet()).isEmpty()) {
                return result;
            }
            Object json = result.remove("json");
            if (json == null) {
                return result;
            }
            ObjectNode jsonNode = (ObjectNode) JsonObject.readTree(json);
            jsonNode.setAll((ObjectNode) JsonObject.readTree(result));
            return fillData(tenantId, appId, tableName, jsonNode);
        }
        Long count = baseMapper.count("<script>select count(*) from (" + script.replace("<script>", "").replace("</script>", "") + ") s</script>", param);
        if (count < 1) {
            return tableApi.startsWith("list") ? null : new PageImpl<>(Collections.emptyList(), Pageable.unpaged(), 0);
        }
        long current = request.path("current").asLong(1);
        long size = request.path("size").asLong(10);
        if (size > 0) {
            if (script.startsWith("<script>")) {
                script = script.substring(0, script.indexOf("</script>")) + " limit " + (current - 1) * size + ", " + size + "</script>";
            } else {
                script += " limit " + (current - 1) * size + ", " + size;
            }
        }
        log.debug("script.{}", script);
        List<Map<String, Object>> mapList = baseMapper.list(script, param);
        if (mapList == null || mapList.isEmpty()) {
            return tableApi.startsWith("list") ? null : new PageImpl<>(Collections.emptyList(), Pageable.unpaged(), 0);
        }
        Map<String, Object> result = mapList.get(0);
        if (!result.containsKey("json") && result.keySet().size() == ignoreFields.size() && !result.keySet().stream().filter(it -> !ignoreFields.contains(it)).collect(Collectors.toSet()).isEmpty()) {
            return mapList;
        }
        List<ObjectNode> dataList = analyse(mapList);
        if (dataList.isEmpty()) {
            return new PageImpl<>(Collections.emptyList(), Pageable.unpaged(), 0);
        }
        List<ObjectNode> recordList = new ArrayList<>();
        for (ObjectNode data : dataList) {
            ObjectNode jsonNode = fillData(tenantId, appId, tableName, data);
            recordList.add(jsonNode.setAll((ObjectNode) objectMapper.valueToTree(data)));
        }
        if (tableApi.startsWith("list")) {
            return recordList;
        }
        return new PageImpl<>(recordList, Pageable.unpaged(), count);
    }

    private List<ObjectNode> analyse(List<Map<String, Object>> dataList) {
        List<ObjectNode> recordList = new ArrayList<>();
        for (Map<String, Object> data : dataList) {
            Object json = data.remove("json");
            ObjectNode dataNode = (ObjectNode) JsonObject.readTree(data);
            if (json == null) {
                recordList.add(dataNode);
            } else {
                ObjectNode jsonNode = (ObjectNode) JsonObject.readTree(json);
                jsonNode.setAll(dataNode);
                recordList.add(jsonNode);
            }
        }
        return recordList;
    }

    public String getScript(String tenantId, String appId, String tableName, String tableApi, Map<String, Object> param) throws IOException {
        log.debug("参数.{}", param);
        String script = discriptService.getScript(tenantId, appId, StringUtils.lowerCamel(tableName), tableApi);
        if (StringUtils.isBlank(script)) {
            script = (String) GroovyUtils.exc(StringUtils.lowerCamel(tableName) + "/" + tableApi + ".groovy", param);
        } else if (!(script.startsWith("<script>") || script.endsWith("</script>"))) {
            script = (String) GroovyUtils.exc(script, param);
        }
//        for (Map.Entry<String, String> entry : param.entrySet()) {
//            script = script.replaceAll("[$][{]" + entry.getKey() + "[}]", entry.getValue());
//        }
        return StringUtils.cut(script, "limit");
    }
}